package com.trainfinder.ripper;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.InvalidParameterException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;

import com.trainfinder.datapersistace.BeanStorage;
import com.trainfinder.datapersistace.BeanStorageFactory;
import com.trainfinder.datapersistace.DataPersitanceException;
import com.trainfinder.datapersistace.Journey;
import com.trainfinder.requestor.IJourney;
import com.trainfinder.requestor.Requestor;
import com.trainfinder.requestor.UnparsableException;


public class Storer {

	public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
			"EEEE, d MMM yyyy HH:MM");

	public static final SimpleDateFormat BOOKING_DATE = new SimpleDateFormat(
			"dd/MM/yyyy");

	private Requestor requestor = new Requestor();

	private  static  final BeanStorage STORAGE = BeanStorageFactory.getInstance();

	private static final long ONE_DAY = 1000L * 60 * 60 * 24;

	// private static final Log LOG = LogFactory.getLog(Storer.class);
	private static final Log LOG = new  MyLog();

	private Date getLastDate() {
		Date result;

		try {
			String bookingPeriodEndMsg = requestor
					.getLastPossibleDate(new LastDateParser());
			LOG.info(bookingPeriodEndMsg);
			System.out.println(bookingPeriodEndMsg);

			String periodEnds = "The booking period ends the";

			int start = bookingPeriodEndMsg.indexOf(periodEnds);
			String date = "";

			if (start != -1) {
				start += periodEnds.length();
				int end = bookingPeriodEndMsg.indexOf(" ", start + 1);
				if (end != -1) {
					date = bookingPeriodEndMsg.substring(start, end).trim();
				}
			}

			result = BOOKING_DATE.parse(date);
		} catch (Exception e) {

			//e.printStackTrace();

			// we will refresh the session.
			requestor = new Requestor();

			Calendar c = Calendar.getInstance();
			c.add(Calendar.MONTH, 2);
			result = c.getTime();
			System.out.println("using default end date of "
					+ DATE_FORMAT.format(result));

			LOG.info("using default end date of " + DATE_FORMAT.format(result));

		}

		return result;
	}

	public void removeExpiredData() {
		STORAGE.removeExpiredData(new Date(new Date().getTime() + ONE_DAY));
	}

	public void dailyStore(Calendar fromCalendar, int durationOfStayInDays,
			String fromStation, String toStation) {

		Calendar c = (Calendar) fromCalendar.clone();
		Calendar returnDate = Calendar.getInstance();

		int hour = 6;

		while (hour < 23) {

			c.set(Calendar.HOUR_OF_DAY, hour);

			List<IJourney> j;
			int old = hour;
			int lastHour = hour;
			try {
				returnDate.setTime(new Date(c.getTime().getTime()
						+ (1000L * 60 * 60 * 24 * durationOfStayInDays)));

				LOG.info("outward scrape : " + DATE_FORMAT.format(c.getTime())
						+ "\nreturn scrape  : "
						+ DATE_FORMAT.format(returnDate.getTime()));

				j = requestor.getJourneis(
						new ExtractStandardTicketValuesImpl(), new DomParser(),
						c, returnDate, fromStation, toStation);

				Journey firstOutward = (Journey) j.get(0);

				final StringBuffer logMessage = new StringBuffer();
				for (Iterator iter = j.iterator(); iter.hasNext();) {
					logMessage.append("\n"
							+ ((IJourney) iter.next()).toString());
				}

				LOG.info(logMessage);

				if (firstOutward.getOutwardOrReturn() == 'R') {
					throw new InvalidParameterException("expected a Outward");
				}

				Journey lastOutward = firstOutward;
				for (Iterator iter = j.iterator(); iter.hasNext();) {
					Journey journey = (Journey) iter.next();
					if (journey.getOutwardOrReturn() == 'R') {
						break;
					} else {
						lastOutward = journey;
					}
				}

				STORAGE.storeAndMerge(j);

				if (firstOutward.id.getDate().getTime() > lastOutward.id
						.getDate().getTime()) {
					throw new InvalidParameterException(
							"expected the date to be greater");
				}

				if (j.size() >= 1) {
					lastHour = lastOutward.getDepartureHour();
				} else {
					lastHour = hour;
				}

			} catch (UnparsableException e) {
				e.printStackTrace();

				StringWriter sw = new StringWriter();
				PrintWriter pw = new PrintWriter(sw, true);
				e.printStackTrace(pw);
				pw.flush();
				sw.flush();

				LOG.info("StackTrace :\n" + sw.toString());
			
				try {
					sw.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
				}
				
				lastHour = hour;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
			}

			hour = lastHour + 1;

			if (hour <= old) {
				hour = old + 1;
			}
			old = hour;

		}

	}

	public void store(String fromStation, String toStation,
			int durationOfStayInDays) {

		Calendar c = Calendar.getInstance();

		Calendar lastCalendar = Calendar.getInstance();
		lastCalendar.setTime(getLastDate());
		lastCalendar.add(Calendar.DAY_OF_YEAR, -durationOfStayInDays);

		long lastTime = lastCalendar.getTime().getTime();

		STORAGE.removeExpiredData(new Date(new Date().getTime() + ONE_DAY));
		while (c.getTime().getTime() < lastTime) {

			dailyStore(c, 1, fromStation, toStation);
			dailyStore(c, durationOfStayInDays, fromStation, toStation);

			c.add(Calendar.DAY_OF_YEAR, 1);
		}
	}

	public void removeDataWithOldLastUpdatedTime(String fromStation,
			String toStation, Date date) {
		STORAGE.removeDataWithOldLastUpdatedTime(fromStation, toStation, date);
	}

	public static final void main(String args[]) {

		// this will insert one line of junk data
		Journey j = new Journey();
		
		try {
			j.id.setDate(BOOKING_DATE.parse("21/10/2006"));
		} catch (ParseException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		j.setFromStation("london");
		j.setToStation("paris");
		j.setWeekendPence(20000);
		j.setOutwardOrReturn('R');
		j.id
				.setTicketType(com.trainfinder.datapersistace.TicketType.NON_FLEXIBLE
						.ordinal());

		Collection<IJourney> c = new ArrayList<IJourney>();
		c.add(j);
		try {
			STORAGE.storeAndMerge(c);
		} catch (DataPersitanceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	 
}
